//
//  socket.c
//  touc
//
//  Created by z on 2020/6/26.
//  Copyright © 2020 z. All rights reserved.
//

#include "socket.h"

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <poll.h>
#include  <stdlib.h>

void structPack(int ty,int64_t a, unsigned char* buf)
{
    if (ty==1)
    {
        uint8_t t=a;
        memcpy(buf,&t,1);
    }
    else if(ty==2)
    {
        uint16_t t=a;
        memcpy(buf,&t,2);
    }
    else if(ty==4)
    {
        uint32_t t=a;
        memcpy(buf,&t,4);
    }
    else if(ty==8)
    {
        int64_t t=a;
        memcpy(buf,&t,8);
    }
}
void structPack_d(int ty,double a, unsigned char* buf)
{
    if (ty==4)
    {
        float t=a;
        memcpy(buf,&t,4);
    }
    else if (ty==8)
    {
        memcpy(buf,&a,8);
    }
}

int64_t structUnpack(int ty,const unsigned char* buf)
{
    if (ty==1)
    {
        uint8_t a;
        memcpy(&a,buf,1);
        return a;
    }
    if (ty==2)
    {
        uint16_t a;
        memcpy(&a,buf,2);
        return a;
    }
    if (ty==4)
    {
        uint32_t a;
        memcpy(&a,buf,4);
        return a;
    }
    if (ty==8)
    {
        int64_t a;
        memcpy(&a,buf,8);
        return a;
    }
    return 0;
}
double structUnpack_d(int ty,const unsigned char* buf)
{
    if (ty==4)
    {
        float a;
        memcpy(&a,buf,4);
        return a;
    }
    if (ty==8)
    {
        double a;
        memcpy(&a,buf,8);
        return a;
    }
    return 0;
}
void setNonblock(int fd)
{
    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
void setDoblock(int fd)
{
    int flags = fcntl(fd, F_GETFL, 0);
       fcntl(fd, F_SETFL, flags &(~O_NONBLOCK));
}
void setNoSig(int so)
{
    int i=1;
    setsockopt(so, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof(i));
}
int makeSock(int type)
{
    int s;
    if (type==0)
        s =  socket (AF_INET, SOCK_STREAM, 0);
    else
        s =  socket (AF_INET, SOCK_DGRAM, 0);
    return s;
}
void closeSock(int so)
{
    close(so);
}
int bindso(int connSock,uint32_t ip,uint16_t port)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    add.sin_addr.s_addr = ip;
    add.sin_port =  htons(port);
    add.sin_family = AF_INET;
    int n =1;
    setsockopt(connSock, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
    int r = bind(connSock, (struct sockaddr *) &add,sizeof(add));
    if (r!=0)
    {
       char*x =  strerror(errno);
    }
    return r;
}

uint16_t getAdd(int so,uint32_t* ip)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    getsockname( so,  (struct sockaddr *)&add,   &addLen);
    *ip=add.sin_addr.s_addr;
    return ntohs(add.sin_port);
}

uint16_t getPeerAdd(int so,uint32_t* ip)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    getpeername( so,  (struct sockaddr *)&add,   &addLen);
    *ip=add.sin_addr.s_addr;
    return ntohs(add.sin_port);
}

int connectso(int so,uint32_t ip,uint16_t port)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    add.sin_addr.s_addr = ip;
    add.sin_port =  htons(port);
    add.sin_family = AF_INET;
    return  connect(so,  (struct sockaddr *)&add, addLen);
}

int listenso(int so,int num)
{
    return  listen(so,num);
}

int acceptso_add(int so,uint32_t* ip,uint16_t* port)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    int r =  accept(so, (struct sockaddr *)&add, &addLen);
    *ip=add.sin_addr.s_addr;
    *port = ntohs(add.sin_port);
    return r;
}
int acceptso(int so)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    return  accept(so, (struct sockaddr *)&add, &addLen);
}
int writetcp(int so,unsigned char* buf,int l)
{
    return  write(so, buf, l);
}

int readtcp(int so,unsigned char* buf,int l )
{
    return  read(so, buf, l);
}
uint32_t ip_str2int(const char* a)
{
    struct in_addr tt;
    inet_aton(a,&tt);
    return tt.s_addr;
}
void writeudp(int so,unsigned char* buf,int l,uint32_t ip,uint16_t port)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    add.sin_addr.s_addr = ip;
    add.sin_port =  htons(port);
    add.sin_family = AF_INET;
    sendto(so, buf, l, 0, (struct sockaddr *)&add, addLen);
}
int readudp(int so,unsigned char* buf,int l)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    int r=  recvfrom(so, buf, l, 0,(struct sockaddr *)&add, &addLen);
    return r;
}
int readudp_add(int so,unsigned char* buf,int l,uint32_t* ip,uint16_t* port)
{
    socklen_t addLen;
    struct sockaddr_in add;
    addLen = sizeof(add);
    int r=  recvfrom(so, buf, l, 0,(struct sockaddr *)&add, &addLen);
    *ip=add.sin_addr.s_addr;
    *port = ntohs(add.sin_port);
    return r;
}

void* openPoll(int n)
{
    return  (void*)malloc(n * sizeof(struct pollfd));
}

void closePoll(void * p)
{
    free(p);
}

void registerPoll(void *p,int pollNum,int fd,int e)
{
    struct pollfd* fds = p;
    fds[pollNum].fd=fd;
    fds[pollNum].events=e;
}

bool getPoll(void *p,int lo,int fd,int e)
{
    struct pollfd* fds = p;
    if(fds[lo].fd==fd&&fds[lo].revents|e)
        return true;
    return false;
}
void getPoll2(void *p,int lo,int *fd,int *e)
{
    struct pollfd* fds = p;
    *fd = fds[lo].fd;
    *e = fds[lo].revents;
}
int doPoll(void *p,int pollNum,int tt)
{
    struct pollfd* fds = p;
    return poll(fds, pollNum,tt );
}
